function sl_customization( cm )

%

cm.addCustomMenuFcn('Simulink:PreContextMenu', @getContextItems);

end

%% Define the custom menu function.
function schemas = getContextItems(callbackInfo)
schemas = {@simulinkLibraryBrowse, ...
          }; 
end


%% Define the schema function for first menu item.
% auto create simulnk library item 
function schema = simulinkLibraryBrowse(callbackInfo)
  % Get mouse position
  mousePosition = get(0,'PointerLocation');
  
  schema = sl_container_schema;
  schema.label = 'Simulink';
  mdl = which('simulink.mdl');
  [blocks,lineInfo]= getMDLInfo(mdl);
  nBlocks = size(lineInfo,1);
  itemIdx = 1;
  for iBlock = 2 : nBlocks 
    rowPos = lineInfo{iBlock,1};
    rowEndPos = lineInfo{iBlock,2};
    if isempty(blocks{rowPos,3}) && rowEndPos == rowPos
      continue;
    end
    
    childrenFcns(itemIdx ) = {{@setSystemItem,{blocks{rowPos,2},iBlock,mdl,mousePosition}}}; 
    itemIdx = itemIdx + 1;
  end
  schema.childrenFcns = childrenFcns;
end

% auto create simulnk block item
% scan subsystem block(none subsystem) and add to item
function schema = setSystemItem(inArgs)

  mousePosition = inArgs.userdata{1,4};
  
  schema = sl_container_schema;
  schema.label = inArgs.userdata{1,1};
  preitemIdx = inArgs.userdata{1,2};
  mdl = inArgs.userdata{1,3};  
  [pathstr, mdlName, ext] = fileparts(mdl);  
  [blocks,lineInfo]= getMDLInfo(mdl);
  itemIdx = 1;
  childrenFcns = {@emptyItem};
  for iPos = lineInfo{preitemIdx,1} : lineInfo{preitemIdx,2}
    if ~isempty(blocks{iPos,3})
      childrenFcns(itemIdx) = {{@addLibraryBlock,{mdlName,blocks{iPos,2} , ...
                                    blocks{iPos,3}, mousePosition}}};
      itemIdx = itemIdx + 1;
    end
  end
  schema.childrenFcns = childrenFcns;
end

function schema = addLibraryBlock(callbackInfo)
  schema = sl_action_schema;
  schema.label = callbackInfo.userdata{3};	
  schema.userdata = callbackInfo.userdata;
  schema.callback = @slAddLibraryBlock; 
end

function schema = emptyItem(callbackInfo)
  schema = sl_action_schema;
  schema.label = '';	
  schema.userdata = '';
  schema.callback = {''}; 
end

% SUB-FUNCTIONS
function slAddLibraryBlock(inArgs)

% Define initial information
modelName     = gcs;
customMDL     = [inArgs.Userdata{1} '/' inArgs.Userdata{2}];
blockName     = inArgs.Userdata{3};
mousePosition = inArgs.Userdata{4};

% Source and destination path
dstStr = [modelName '/' blockName];
srcStr = [customMDL '/' blockName];

% Get more information for position calculation
blockSizeRef = get_param(srcStr, 'Position');
locationBase = get_param(modelName,'Location');
scrollOffset = get_param(modelName,'ScrollbarOffset');
screenSize   = get(0,'ScreenSize');

% Calculate new position
p_X = mousePosition(1) - locationBase(1) + scrollOffset(1);
p_Y = screenSize(4) - mousePosition(2) - locationBase(2) + scrollOffset(2) ;
width = blockSizeRef(3) - blockSizeRef(1);
height = blockSizeRef(4) - blockSizeRef(2);
location = [p_X p_Y p_X+width p_Y+height];

% Add block
block = add_block(srcStr, dstStr, 'MakeNameUnique', 'on');
set(block, 'Position', location);

close_system(customMDL);
        
end

function [blocks,lineInfo] = getMDLInfo(mdl)
  load_system(mdl);  
  blocks = find_system(gcs,'SearchDepth',2);
  nBlocks = length(blocks);
  
  for iBlock = 1 : nBlocks
    str = regexp(blocks{iBlock,1}, '/', 'split');
    for iStr = 1 : length(str)
      blocks{iBlock,iStr} = str{1,iStr};
    end
  end
  itemIdx = 1;
  preItemNmae = 'null'; % for safety, when the first item name is empty
  itemLineStart = 1;
  for iBlock = 1 : length(blocks)
    if ~isempty(blocks{iBlock,2}) && ~strcmp(blocks{iBlock,2},preItemNmae)
      itemLineStart = iBlock;
      childrenFcns(itemIdx) = {{@setSystemItem,blocks{iBlock,2}}};
      preItemNmae = blocks{iBlock,2};
      itemIdx = itemIdx + 1;      
    end
    itemLineEnd = iBlock;
    lineInfo{itemIdx,1} = itemLineStart;
    lineInfo{itemIdx,2} = itemLineEnd;
  end
end